package com.blog.cmrpersonalblog.service.impl;

import com.blog.cmrpersonalblog.config.FileUploadConfig;
import com.blog.cmrpersonalblog.dto.comment.responst.CommentImageInfo;
import com.blog.cmrpersonalblog.dto.comment.responst.CommentImageUploadResponse;
import com.blog.cmrpersonalblog.entity.CommentImage;
import com.blog.cmrpersonalblog.entity.CommentImageTemp;
import com.blog.cmrpersonalblog.mapper.CommentImageMapper;
import com.blog.cmrpersonalblog.mapper.CommentImageTempMapper;
import com.blog.cmrpersonalblog.mapper.CommentMapper;
import com.blog.cmrpersonalblog.service.CommentImageService;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 评论图片服务实现类
 */
@Slf4j
@Service
public class CommentImageServiceImpl implements CommentImageService {

   @Resource
    private CommentImageMapper commentImageMapper;

   @Resource
    private CommentImageTempMapper commentImageTempMapper;

   @Resource
    private CommentMapper commentMapper;

   @Resource
    private FileUploadConfig fileUploadConfig;

   @Resource
    private ObjectMapper objectMapper;

    @Override
    public CommentImageUploadResponse uploadCommentImage(MultipartFile file, Long userId, String uploadToken) {
        try {
            // 验证文件
            if (!isValidCommentImage(file)) {
                return new CommentImageUploadResponse(false, "不支持的文件类型或文件格式无效");
            }

            // 检查文件大小
            if (file.getSize() > fileUploadConfig.getMaxCommentImageSize()) {
                return new CommentImageUploadResponse(false, "文件大小超过限制（最大10MB）");
            }

            // 创建上传目录
            String uploadPath = fileUploadConfig.getCommentImageFullPath();
            File uploadDir = new File(uploadPath);
            if (!uploadDir.exists()) {
                boolean created = uploadDir.mkdirs();
                if (!created) {
                    return new CommentImageUploadResponse(false, "创建上传目录失败");
                }
            }

            // 生成文件名和令牌
            String fileName = generateCommentImageFileName(file.getOriginalFilename(), userId);
            if (!StringUtils.hasText(uploadToken)) {
                uploadToken = generateUploadToken(userId);
            }

            // 构建文件路径
            Path filePath = Paths.get(uploadPath, fileName);

            // 保存文件
            Files.copy(file.getInputStream(), filePath);

            // 构建相对路径和访问URL
            String relativePath = fileUploadConfig.getCommentImagePath() + "/" + fileName;
            String fileUrl = fileUploadConfig.getFileUrl(relativePath);

            // 创建临时图片记录
            CommentImageTemp tempImage = new CommentImageTemp();
            tempImage.setUserId(userId);
            tempImage.setFileName(fileName);
            tempImage.setOriginalName(file.getOriginalFilename());
            tempImage.setFileSize(file.getSize());
            tempImage.setContentType(file.getContentType());
            tempImage.setRelativePath(relativePath);
            tempImage.setFileUrl(fileUrl);
            tempImage.setUploadToken(uploadToken);
            // 设置过期时间为24小时后
            tempImage.setExpireTime(LocalDateTime.now().plusHours(24));

            commentImageTempMapper.insert(tempImage);

            // 构建响应
            CommentImageInfo imageInfo = new CommentImageInfo();
            imageInfo.setId(tempImage.getId());
            imageInfo.setFileName(fileName);
            imageInfo.setOriginalName(file.getOriginalFilename());
            imageInfo.setFileSize(file.getSize());
            imageInfo.setContentType(file.getContentType());
            imageInfo.setRelativePath(relativePath);
            imageInfo.setFileUrl(fileUrl);
            imageInfo.setUploadTime(System.currentTimeMillis());

            log.info("评论图片上传成功: userId={}, fileName={}, tempImageId={}", 
                    userId, fileName, tempImage.getId());

            return new CommentImageUploadResponse(true, "图片上传成功", uploadToken, imageInfo, tempImage.getId());

        } catch (IOException e) {
            log.error("评论图片上传失败: userId={}", userId, e);
            return new CommentImageUploadResponse(false, "文件上传失败: " + e.getMessage());
        } catch (Exception e) {
            log.error("评论图片上传异常: userId={}", userId, e);
            return new CommentImageUploadResponse(false, "上传失败，请稍后重试");
        }
    }

    @Override
    @Transactional
    public boolean attachImagesToComment(Long commentId, List<Long> tempImageIds, Long userId) {
        try {
            if (tempImageIds == null || tempImageIds.isEmpty()) {
                return true;
            }

            // 检查数量限制
            if (tempImageIds.size() > fileUploadConfig.getMaxImagesPerComment()) {
                throw new RuntimeException("图片数量超过限制（最多" + fileUploadConfig.getMaxImagesPerComment() + "张）");
            }

            // 获取临时图片
            List<CommentImageTemp> tempImages = commentImageTempMapper.selectByIdsAndUserId(tempImageIds, userId);
            if (tempImages.isEmpty()) {
                return false;
            }

            // 过滤过期图片
            List<CommentImageTemp> validImages = tempImages.stream()
                    .filter(img -> !img.isExpired())
                    .collect(Collectors.toList());

            if (validImages.isEmpty()) {
                throw new RuntimeException("所选图片已过期，请重新上传");
            }

            // 转换为正式图片记录
            List<CommentImage> commentImages = new ArrayList<>();
            List<CommentImageInfo> imageInfos = new ArrayList<>();
            
            for (int i = 0; i < validImages.size(); i++) {
                CommentImageTemp tempImage = validImages.get(i);
                
                CommentImage commentImage = new CommentImage();
                commentImage.setCommentId(commentId);
                commentImage.setUserId(userId);
                commentImage.setFileName(tempImage.getFileName());
                commentImage.setOriginalName(tempImage.getOriginalName());
                commentImage.setFileSize(tempImage.getFileSize());
                commentImage.setContentType(tempImage.getContentType());
                commentImage.setRelativePath(tempImage.getRelativePath());
                commentImage.setFileUrl(tempImage.getFileUrl());
                commentImage.setWidth(tempImage.getWidth());
                commentImage.setHeight(tempImage.getHeight());
                commentImage.setSortOrder(i);
                commentImage.setStatus(1);

                commentImages.add(commentImage);

                // 构建图片信息用于JSON存储
                CommentImageInfo imageInfo = new CommentImageInfo();
                imageInfo.setFileName(tempImage.getFileName());
                imageInfo.setOriginalName(tempImage.getOriginalName());
                imageInfo.setFileSize(tempImage.getFileSize());
                imageInfo.setContentType(tempImage.getContentType());
                imageInfo.setRelativePath(tempImage.getRelativePath());
                imageInfo.setFileUrl(tempImage.getFileUrl());
                imageInfo.setWidth(tempImage.getWidth());
                imageInfo.setHeight(tempImage.getHeight());
                imageInfo.setSortOrder(i);

                imageInfos.add(imageInfo);
            }

            // 批量插入图片记录
            commentImageMapper.insertBatch(commentImages);

            // 更新评论表的图片字段
            updateCommentImages(commentId, imageInfos);

            // 删除临时图片记录
            commentImageTempMapper.deleteByIdsAndUserId(tempImageIds, userId);

            log.info("图片关联到评论成功: commentId={}, userId={}, imageCount={}", 
                    commentId, userId, validImages.size());

            return true;

        } catch (Exception e) {
            log.error("图片关联到评论失败: commentId={}, userId={}", commentId, userId, e);
            throw new RuntimeException("图片关联失败: " + e.getMessage());
        }
    }

    @Override
    @Transactional
    public boolean attachImagesByTokens(Long commentId, List<String> uploadTokens, Long userId) {
        try {
            if (uploadTokens == null || uploadTokens.isEmpty()) {
                return true;
            }

            // 获取临时图片
            List<CommentImageTemp> tempImages = commentImageTempMapper.selectByTokensAndUserId(uploadTokens, userId);
            if (tempImages.isEmpty()) {
                return false;
            }

            // 提取图片ID
            List<Long> tempImageIds = tempImages.stream()
                    .map(CommentImageTemp::getId)
                    .collect(Collectors.toList());

            return attachImagesToComment(commentId, tempImageIds, userId);

        } catch (Exception e) {
            log.error("根据令牌关联图片失败: commentId={}, userId={}", commentId, userId, e);
            throw new RuntimeException("图片关联失败: " + e.getMessage());
        }
    }

    @Override
    public List<CommentImageInfo> getCommentImages(Long commentId) {
        try {
            List<CommentImage> images = commentImageMapper.selectByCommentId(commentId);
            return images.stream()
                    .filter(CommentImage::isNormal)
                    .sorted(Comparator.comparing(CommentImage::getSortOrder, Comparator.nullsLast(Integer::compareTo)))
                    .map(this::convertToImageInfo)
                    .collect(Collectors.toList());
        } catch (Exception e) {
            log.error("获取评论图片失败: commentId={}", commentId, e);
            return new ArrayList<>();
        }
    }

    @Override
    public Map<Long, List<CommentImageInfo>> getBatchCommentImages(List<Long> commentIds) {
        try {
            if (commentIds == null || commentIds.isEmpty()) {
                return new HashMap<>();
            }
            
            // 去重并过滤null值
            List<Long> validCommentIds = commentIds.stream()
                    .filter(Objects::nonNull)
                    .distinct()
                    .collect(Collectors.toList());
            
            if (validCommentIds.isEmpty()) {
                return new HashMap<>();
            }
            
            // 批量查询所有图片
            List<CommentImage> allImages = commentImageMapper.selectByCommentIds(validCommentIds);
            log.info("批量查询评论图片: commentIds count={}, images count={}", validCommentIds.size(), allImages.size());
            
            // 按评论ID分组，并过滤正常状态的图片
            Map<Long, List<CommentImageInfo>> result = allImages.stream()
                    .filter(CommentImage::isNormal)
                    .collect(Collectors.groupingBy(
                            CommentImage::getCommentId,
                            Collectors.mapping(
                                    image -> this.convertToImageInfo(image),
                                    Collectors.collectingAndThen(
                                            Collectors.toList(),
                                            list -> list.stream()
                                                    .sorted(Comparator.comparing(CommentImageInfo::getSortOrder, 
                                                            Comparator.nullsLast(Integer::compareTo)))
                                                    .collect(Collectors.toList())
                                    )
                            )
                    ));
            
            // 确保所有请求的评论ID都有对应的条目（即使是空列表）
            for (Long commentId : validCommentIds) {
                result.putIfAbsent(commentId, new ArrayList<>());
            }
            
            return result;
        } catch (Exception e) {
            log.error("批量获取评论图片失败: commentIds={}", commentIds, e);
            return new HashMap<>();
        }
    }

    @Override
    @Transactional
    public boolean deleteCommentImage(Long imageId, Long userId) {
        try {
            // 更新图片状态为已删除
            int updated = commentImageMapper.updateStatusById(imageId, 0, userId);
            if (updated > 0) {
                log.info("评论图片删除成功: imageId={}, userId={}", imageId, userId);
                return true;
            }
            return false;
        } catch (Exception e) {
            log.error("删除评论图片失败: imageId={}, userId={}", imageId, userId, e);
            return false;
        }
    }

    @Override
    @Transactional
    public boolean deleteAllCommentImages(Long commentId, Long userId) {
        try {
            int deleted = commentImageMapper.deleteByCommentIdAndUserId(commentId, userId);
            log.info("删除评论所有图片: commentId={}, userId={}, count={}", commentId, userId, deleted);
            return true;
        } catch (Exception e) {
            log.error("删除评论所有图片失败: commentId={}, userId={}", commentId, userId, e);
            return false;
        }
    }

    @Override
    @Transactional
    public boolean updateCommentImagesStatus(Long commentId, Integer status) {
        try {
            int updated = commentImageMapper.updateStatusByCommentId(commentId, status);
            log.info("更新评论图片状态: commentId={}, status={}, count={}", commentId, status, updated);
            return true;
        } catch (Exception e) {
            log.error("更新评论图片状态失败: commentId={}, status={}", commentId, status, e);
            return false;
        }
    }

    @Override
    @Transactional
    public boolean updateCommentsImagesStatus(List<Long> commentIds, Integer status) {
        try {
            if (commentIds == null || commentIds.isEmpty()) {
                return true;
            }
            int updated = commentImageMapper.updateStatusByCommentIds(commentIds, status);
            log.info("批量更新评论图片状态: commentIds={}, status={}, count={}", commentIds, status, updated);
            return true;
        } catch (Exception e) {
            log.error("批量更新评论图片状态失败: commentIds={}, status={}", commentIds, status, e);
            return false;
        }
    }

    @Override
    @Transactional
    public int cleanExpiredTempImages() {
        try {
            LocalDateTime expireTime = LocalDateTime.now();
            int deleted = commentImageTempMapper.deleteExpired(expireTime);
            if (deleted > 0) {
                log.info("清理过期临时图片完成: count={}", deleted);
            }
            return deleted;
        } catch (Exception e) {
            log.error("清理过期临时图片失败", e);
            return 0;
        }
    }

    @Override
    public String generateUploadToken(Long userId) {
        String timestamp = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));
        String uuid = UUID.randomUUID().toString().replace("-", "");
        return "comment_" + userId + "_" + timestamp + "_" + uuid.substring(0, 8);
    }

    @Override
    public boolean isValidCommentImage(MultipartFile file) {
        if (file == null || file.isEmpty()) {
            return false;
        }

        // 检查文件类型
        String contentType = file.getContentType();
        if (!fileUploadConfig.isAllowedImageType(contentType)) {
            return false;
        }

        // 检查文件扩展名
        String originalFileName = file.getOriginalFilename();
        if (!fileUploadConfig.isAllowedExtension(originalFileName)) {
            return false;
        }

        return true;
    }

    @Override
    public String generateCommentImageFileName(String originalFileName, Long userId) {
        // 获取文件扩展名
        String extension = getFileExtension(originalFileName);
        
        // 生成时间戳
        String timestamp = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));
        
        // 生成UUID
        String uuid = UUID.randomUUID().toString().replace("-", "");
        
        // 构建文件名：comment_用户ID_时间戳_UUID.扩展名
        StringBuilder fileName = new StringBuilder("comment");
        if (userId != null) {
            fileName.append("_").append(userId);
        }
        fileName.append("_").append(timestamp);
        fileName.append("_").append(uuid.substring(0, 8));
        fileName.append(extension);
        
        return fileName.toString();
    }

    @Override
    public List<CommentImageInfo> getUserTempImages(Long userId, String uploadToken) {
        try {
            List<CommentImageTemp> tempImages;
            if (StringUtils.hasText(uploadToken)) {
                tempImages = commentImageTempMapper.selectByUserIdAndToken(userId, uploadToken);
            } else {
                tempImages = commentImageTempMapper.selectByUserId(userId);
            }

            return tempImages.stream()
                    .filter(img -> !img.isExpired())
                    .map(this::convertTempToImageInfo)
                    .collect(Collectors.toList());
        } catch (Exception e) {
            log.error("获取用户临时图片失败: userId={}, uploadToken={}", userId, uploadToken, e);
            return new ArrayList<>();
        }
    }

    /**
     * 更新评论表的图片字段
     */
    private void updateCommentImages(Long commentId, List<CommentImageInfo> imageInfos) {
        try {
            String imagesJson = objectMapper.writeValueAsString(imageInfos);
            
            // 使用原生SQL更新
            commentMapper.updateCommentImages(commentId, imagesJson, imageInfos.size());
            
        } catch (Exception e) {
            log.error("更新评论图片字段失败: commentId={}", commentId, e);
            throw new RuntimeException("更新评论图片信息失败");
        }
    }

    /**
     * 转换CommentImage为CommentImageInfo
     */
    private CommentImageInfo convertToImageInfo(CommentImage image) {
        CommentImageInfo info = new CommentImageInfo();
        info.setId(image.getId());
        info.setFileName(image.getFileName());
        info.setOriginalName(image.getOriginalName());
        info.setFileSize(image.getFileSize());
        info.setContentType(image.getContentType());
        info.setRelativePath(image.getRelativePath());
        info.setFileUrl(image.getFileUrl());
        info.setWidth(image.getWidth());
        info.setHeight(image.getHeight());
        info.setSortOrder(image.getSortOrder());
        info.setUploadTime(image.getCreateTime() != null ? 
                image.getCreateTime().atZone(java.time.ZoneId.systemDefault()).toInstant().toEpochMilli() : null);
        return info;
    }

    /**
     * 转换CommentImageTemp为CommentImageInfo
     */
    private CommentImageInfo convertTempToImageInfo(CommentImageTemp tempImage) {
        CommentImageInfo info = new CommentImageInfo();
        info.setId(tempImage.getId());
        info.setFileName(tempImage.getFileName());
        info.setOriginalName(tempImage.getOriginalName());
        info.setFileSize(tempImage.getFileSize());
        info.setContentType(tempImage.getContentType());
        info.setRelativePath(tempImage.getRelativePath());
        info.setFileUrl(tempImage.getFileUrl());
        info.setWidth(tempImage.getWidth());
        info.setHeight(tempImage.getHeight());
        info.setUploadTime(tempImage.getCreateTime() != null ? 
                tempImage.getCreateTime().atZone(java.time.ZoneId.systemDefault()).toInstant().toEpochMilli() : null);
        return info;
    }

    /**
     * 获取文件扩展名
     */
    private String getFileExtension(String fileName) {
        if (!StringUtils.hasText(fileName)) {
            return "";
        }
        
        int lastDotIndex = fileName.lastIndexOf(".");
        if (lastDotIndex == -1) {
            return "";
        }
        
        return fileName.substring(lastDotIndex).toLowerCase();
    }
}
